#include "FleetMove.hh"
#include "Done.hh"
#include "XmlServerThread.hh"
#include "../World/Fleet.hh"
#include "../World/Fleet/Move.hh"
#include "../Exception.hh"

#define ERROR(NAME, MESSAGE)                                            \
    struct NAME##Invalid {                                              \
        void operator () () {                                           \
            throw                                                       \
              NonFatalProtocolError(                                    \
                "game.fleet_move." + QString((MESSAGE)) + " invalid"    \
              );                                                        \
        }                                                               \
    }                                                                   \


using namespace Geom;
using namespace Network;
using namespace World;

ERROR(FId,   "id");
ERROR(FDest, "dest");

FleetMove::FleetMove(u8 id, Vector< f8 > const& destination):
    id(id),
    destination(destination) {}

spFleetMove FleetMove::construct(QDomElement const& message) {
    QDomElement const idElem = message.firstChildElement("id");
    QDomElement const destElem = message.firstChildElement("dest");
    u8 const id = parse_num< u8, FIdInvalid >(idElem);
    Vector< f8 > dest;

    if (!dest.from_xml(destElem))
        throw NonFatalProtocolError("game.fleet_move.dest invalid");

    return spFleetMove(new FleetMove(id, dest));
}

void FleetMove::process_on_server(XmlServerThread& thread) {
    if (thread.get_state() != GAME)
        throw NonFatalProtocolError("game.fleet_move unexpected");

    try {
        spFleet fleet = thread.get_player()->get_fleet(id);
        fleet->set_command(new Fleet::Move(destination));
        Done done(true, "game.fleet_move ok");
        done.send_to(*thread.get_socket());
    } catch (FleetNotFound& ex) {
        Done done(false, ex.what());
        done.send_to(*thread.get_socket());
    }
}

QDomDocument FleetMove::to_xml() const {
    QDomDocument doc;
    QDomElement gameElem = doc.createElement("game");
    QDomElement fleetMoveElem = doc.createElement("fleet_move");
    doc.appendChild(gameElem);
    gameElem.appendChild(fleetMoveElem);
    ::to_xml(fleetMoveElem, "id", id);
    destination.to_xml(fleetMoveElem, "dest");
    return doc;
}
